<?php

namespace plugin\ycMassage\app\model;

use app\common\service\UploadService;
use plugin\ycMassage\utils\enum\ActionIdentity;
use plugin\ycMassage\utils\enum\NoticeType;
use plugin\ycMassage\utils\enum\OrdersState;
use plugin\ycMassage\utils\enum\ServiceState;
use plugin\ycMassage\utils\enum\State;
use plugin\ycMassage\utils\notice\Notice;
use think\Exception;
use think\facade\Db;

class MassageAppointmentService extends Model
{
    public function getNicknameAttr($value)
    {
        return base64_decode($value);
    }
    public function getHeadimgAttr($value)
    {
        # 判断是否为url
        if (strpos($value, 'http') === 0) {
            return $value;
        }
        return $value ? UploadService::url($value) : '';
    }
    public function getArrivalPhotoAttr($value)
    {
        return $value ? UploadService::url($value) : '';
    }
    public function getServiceStartPhotoAttr($value)
    {
        return $value ? UploadService::url($value) : '';
    }
    public function getServiceEndPhotoAttr($value)
    {
        return $value ? UploadService::url($value) : '';
    }
    const RSERVATION_DURATION = 30;
    public static function createMatrix($scheduling_id, $start_time, $end_time, $duration_step = 10)
    {
        # 创建一个时间矩阵，每10分钟一个格子
        $matrix = [];
        $start_time = strtotime($start_time);
        $end_time = strtotime($end_time);
        $time = $start_time;
        # 查询已经预约的时间
        $data = self::where('scheduling_id', $scheduling_id)->select();
        # data start_time：预约时间 duration：时长(分钟) commuting_duration：上班时间(分钟)
        $appointments = [];
        foreach ($data as $item) {
            $appointments[] = [
                'start_time' => strtotime($item->start_time),
                'end_time' => strtotime($item->start_time) + $item->duration * 60 + $item->commuting_duration * 60,
            ];
        }
        while ($time < $end_time) {
            $temp = [
                'id' => $scheduling_id,
                'start_time' => date('Y-m-d H:i:s', $time),
                'end_time' => date('Y-m-d H:i:s', $time + $duration_step * 60),
                'duration' => $duration_step,
                'state' => $time < time() ? 1 : 0,
            ];
            # 判断是否已经预约
            foreach ($appointments as $appointment) {
                if ($time >= $appointment['start_time'] && $time < $appointment['end_time']) {
                    $temp['state'] = 2;
                    break;
                }
            }
            $matrix[] = $temp;
            $time += ($duration_step * 60);
        }
        return $matrix;
    }
    public static function hasReservation($scheduling_id, $start_time, $end_time, $time, $service_duration)
    {
        $Matrix = self::createMatrix($scheduling_id, $start_time, $end_time, self::RSERVATION_DURATION);
        $duration = 0;
        foreach ($Matrix as $item) {
            if ($item['start_time'] == $time && $item['state'] === 0) {
                $duration = $item['duration'];
                continue;
            }
            if ($duration > 0) {
                if ($item['state'] === 0) {
                    $duration += $item['duration'];
                    if ($duration >= $service_duration) {
                        return true;
                    }
                } else {
                    return false;
                }
            }
        }
        if ($duration > 0) {
            return true;
        }
        return false;
    }
    public static function endService($options)
    {
        $where = [
            ['id', '=', $options->id],
            ['saas_appid', '=', $options->saas_appid]
        ];
        if ($options->action === 'user') {
            $where[] = ['uid', '=', $options->uid];
        } else {
            $where[] = ['technician_id', '=', $options->uid];
        }
        Db::startTrans();
        try {
            $model = MassageAppointmentService::where($where)->lock(true)->find();
            if (!$model) {
                throw new \Exception('服务不存在');
            }
            if ($model->state != ServiceState::ING['value']) {
                throw new \Exception('服务状态异常,请刷新查看');
            }
            $model->state = ServiceState::FINISH['value'];
            $model->service_end_time = date('Y-m-d H:i:s');
            if(isset($options->service_end_photo)){
                $model->service_end_photo = $options->service_end_photo;
            }
            $model->save();
            # 技师
            $MassageUserTechnician = MassageUserTechnician::where(['uid' => $model->technician_id])->find();
            $person_time = 0;
            # 子订单处理
            $MassageOrdersSub = MassageOrdersSub::where(['id' => $model->orders_sub_id])->find();
            $MassageOrdersSub->state = OrdersState::WAIT_COMMENT['value'];
            $MassageOrdersSub->save();
            $MassageOrders = MassageOrders::where(['id' => $model->orders_id])->find();
            $MassageUserTechnician->order_num = Db::raw('order_num+1');
            # 主订单处理
            if (!MassageOrdersSub::where(['orders_id' => $model->orders_id, 'state' => OrdersState::SERVICE_ING['value']])->count()) {
                $MassageOrders->state = OrdersState::WAIT_COMMENT['value'];
                $MassageOrders->finish_time = date('Y-m-d H:i:s');
                $MassageOrders->save();
                $MassageUserTechnician->people_num = Db::raw('people_num+1');
                $person_time = 1;
            }
            # 技师统计
            $MassageUserTechnicianStatistics = MassageUserTechnicianStatistics::where(['saas_appid' => $model->saas_appid, 'uid' => $model->technician_id])->whereDay('create_time')->find();
            if (!$MassageUserTechnicianStatistics) {
                $MassageUserTechnicianStatistics = new MassageUserTechnicianStatistics;
                $MassageUserTechnicianStatistics->uid = $model->technician_id;
                $MassageUserTechnicianStatistics->saas_appid = $model->saas_appid;
            }
            # 加钟订单
            $MassageOrdersSubOvertime = MassageOrdersSub::where(['appointment_service_id' => $model->id, 'state' => OrdersState::SERVICE_ING['value']])->select();
            $overtimePrice = 0;
            foreach ($MassageOrdersSubOvertime as $item) {
                $overtimePrice += $item->price;
                $item->state = OrdersState::FINISH['value'];
                $item->save();
            }
            # 加钟主订单处理
            if (!MassageOrdersSub::where(['appointment_service_id' => $model->id, 'state' => OrdersState::SERVICE_ING['value']])->count()) {
                $OvertimeOrders = MassageOrders::where(['orders_id' => $MassageOrders->id, 'state' => OrdersState::SERVICE_ING['value']])->select();
                foreach ($OvertimeOrders as $item) {
                    $item->state = OrdersState::WAIT_COMMENT['value'];
                    $item->finish_time = date('Y-m-d H:i:s');
                    $item->save();
                }
            }
            # 订单数
            $MassageUserTechnicianStatistics->order_num = Db::raw('order_num+1');
            # 订单金额
            $price = $MassageOrdersSub->price + $overtimePrice;
            $MassageUserTechnicianStatistics->order_price = Db::raw('order_price+' . $price);
            # 服务时长
            $MassageUserTechnicianStatistics->duration = Db::raw('duration+' . $model->duration);
            # 新客
            if (!MassageAppointmentService::where(['uid' => $model->uid, 'technician_id' => $model->technician_id])
                ->where('orders_id', '<>', $model->orders_id)->where('state', '>', ServiceState::NOT_PAY['value'])->count()) {
                $MassageUserTechnicianStatistics->new_customers = Db::raw('new_customers+1');
            }
            $transaction_freeze_period = getHpConfig('transaction_freeze_period', $options->saas_appid, 'orders');
            # 渠道分成
            $technician_commission = 0;
            if ($MassageOrdersSub->channels_id) {
                $new_customers = 0;
                if (!MassageOrders::where(['uid' => $model->uid, 'channels_id' => $MassageOrdersSub->channels_id])
                    ->where('orders_id', '<>', $model->orders_id)->where('state', '>', ServiceState::NOT_PAY['value'])->count()) {
                    $new_customers = 1;
                }
                $technician_commission = MassageUserChannels::commission($model, [
                    'price' => $price,
                    'trade' => $MassageOrders->trade,
                    'channels_id' => $MassageOrdersSub->channels_id,
                    'transaction_freeze_period' => $transaction_freeze_period,
                    'statistics' => [
                        'order_num' => 1,
                        'order_price' => $price,
                        'duration' => $model->duration,
                        'new_customers' => $new_customers
                    ]
                ]);
            }
            $MassageUser = MassageUser::alias('u')->where(['u.id' => $model->uid])
                ->join('MassageUserWechat uw', 'uw.uid=u.id', 'left')
                ->field('u.dealer_uid,u.mobile,uw.openid')
                ->find();
            if ($MassageUser->dealer_uid) {
                $technician_commission+=MassageUserDealer::commission($MassageUser->dealer_uid, $MassageOrdersSub, $transaction_freeze_period);
            }
            $MassageUserT = MassageUser::alias('u')->where(['u.id' => $model->technician_id])
                ->join('MassageUserWechat uw', 'uw.uid=u.id', 'left')
                ->field('u.dealer_uid,u.nickname,u.mobile,uw.openid')
                ->find();
            if ($MassageUserT->dealer_uid) {
                $technician_commission+=MassageUserDealer::commission($MassageUserT->dealer_uid, $MassageOrdersSub, $transaction_freeze_period,'technician_');
            }
            # 技师或商户分佣
            $MassageService = MassageService::where(['id' => $model->service_id])->find();
            if ($MassageUserTechnician->work_mch_id || $MassageUserTechnician->work_shop_id) {
                $commission = round($price * $MassageService->mch_commission / 100, 2);
                # 当存在代理时，减去代理分成
                if ($technician_commission > 0) {
                    $commission = $commission - $technician_commission;
                }
                $where = ['mch_id' => $MassageUserTechnician->work_mch_id];
                if ($MassageUserTechnician->work_shop_id) {
                    $where['shop_id'] = $MassageUserTechnician->work_shop_id;
                }
                $MassageShopStatistics = MassageShopStatistics::where($where)->find();
                if (!$MassageShopStatistics) {
                    $MassageShopStatistics = new MassageShopStatistics();
                    $MassageShopStatistics->saas_appid = $model->saas_appid;
                    $MassageShopStatistics->mch_id = $MassageUserTechnician->work_mch_id;
                    $MassageShopStatistics->shop_id = $MassageUserTechnician->work_shop_id;
                }
                if ($person_time > 0) {
                    $MassageShopStatistics->person_time = Db::raw('person_time+' . $person_time);
                }
                $MassageShopStatistics->duration = Db::raw('duration+' . $model->duration);
                $MassageShopStatistics->orders_num = Db::raw('orders_num+1');
                $MassageShopStatistics->orders_price = Db::raw('orders_price+' . $price);
                $MassageShopStatistics->save();
                $MassageMch = MassageMch::where(['id' => $MassageUserTechnician->work_mch_id])->find();
                # 商户分佣逻辑
                if ($MassageOrdersSub->material_price > 0) {
                    MassageMchBill::increase("订单：{$MassageOrders->trade} - {$MassageOrdersSub->id}材料费，{$MassageMch->title}商户", $MassageMch->uid, $MassageOrdersSub->material_price, $model->id);
                }
                $remarks = "完成订单，订单号：{$MassageOrders->trade}，{$MassageMch->title}商户";
                if ($transaction_freeze_period) {
                    $MassageUserWallet = MassageUserWallet::where(['uid' => $model->technician_id])->lock(true)->find();
                    if (!$MassageUserWallet) {
                        throw new Exception('用户钱包不存在');
                    }
                    $MassageUserFreezeMoney = new MassageUserFreezeMoney();
                    $MassageUserFreezeMoney->uid = $MassageMch->uid;
                    $MassageUserFreezeMoney->form_uid = $model->id;
                    $MassageUserFreezeMoney->saas_appid = $options->saas_appid;
                    $MassageUserFreezeMoney->action = ActionIdentity::MCH['value'];
                    $MassageUserFreezeMoney->money = $commission;
                    $MassageUserFreezeMoney->orders_id = $model->orders_id;
                    $MassageUserFreezeMoney->state = State::NO['value'];
                    $MassageUserFreezeMoney->unfreezing_time = date('Y-m-d H:i:s', strtotime("+{$transaction_freeze_period} hours"));
                    $MassageUserFreezeMoney->remarks = $remarks;
                    $MassageUserFreezeMoney->save();
                    $MassageUserWallet->mch_freeze_money = Db::raw('mch_freeze_money+' . $commission);
                    $MassageUserWallet->save();
                } else {
                    MassageMchBill::increase($remarks, $MassageMch->uid, $commission, $model->id);
                }
                # 商户分佣逻辑
            } else {
                $commission = round($price * $MassageService->technician_commission / 100, 2);
                # 当存在代理时，减去代理分成
                if ($technician_commission > 0) {
                    $commission = $commission - $technician_commission;
                }
                # 技师分佣逻辑
                $remarks = '完成订单，订单号：' . $MassageOrders->trade;
                if ($transaction_freeze_period) {
                    $MassageUserWallet = MassageUserWallet::where(['uid' => $model->technician_id])->lock(true)->find();
                    if (!$MassageUserWallet) {
                        throw new Exception('用户钱包不存在');
                    }
                    $MassageUserFreezeMoney = new MassageUserFreezeMoney();
                    $MassageUserFreezeMoney->uid = $model->technician_id;
                    $MassageUserFreezeMoney->form_uid = $model->uid;
                    $MassageUserFreezeMoney->saas_appid = $options->saas_appid;
                    $MassageUserFreezeMoney->action = ActionIdentity::TECHNICIAN['value'];
                    $MassageUserFreezeMoney->money = $commission;
                    $MassageUserFreezeMoney->orders_id = $model->orders_id;
                    $MassageUserFreezeMoney->state = State::NO['value'];
                    $MassageUserFreezeMoney->unfreezing_time = date('Y-m-d H:i:s', strtotime("+{$transaction_freeze_period} hours"));
                    $MassageUserFreezeMoney->remarks = $remarks;
                    $MassageUserFreezeMoney->save();
                    $MassageUserWallet->technician_freeze_money = Db::raw('technician_freeze_money+' . $commission);
                    $MassageUserWallet->save();
                } else {
                    MassageUserTechnicianBill::increase($remarks, $model->technician_id, $commission, $model->uid);
                }
                # 技师分佣逻辑
                $MassageUserTechnicianStatistics->commission = Db::raw('commission+' . $commission);
            }
            $MassageUserTechnicianStatistics->save();
            if ($options->latitude && $options->longitude) {
                # 技师
                $MassageUserTechnician->latitude = $options->latitude;
                $MassageUserTechnician->longitude = $options->longitude;
            }
            $MassageUserTechnician->save();
            $MassageUser = MassageUser::where(['id' => $model->uid])->find();
            # 用户首单
            $new_customers = 0;
            if (!MassageAppointmentService::where(['uid' => $model->uid])
                ->where('orders_id', '<>', $model->orders_id)->where('state', '>', ServiceState::NOT_PAY['value'])->count()) {
                $new_customers = 1;
                if ($MassageUser->puid) {
                    $pModel = MassageUser::where(['id' => $MassageUser->puid])->find();
                    MassageUser::NewFirstOrderGift($MassageUser, $pModel);
                }
            }
            # 代理分成
            MassageUserAgent::commission($model, [
                'price' => $price,
                'trade' => $MassageOrders->trade,
                'transaction_freeze_period' => $transaction_freeze_period,
                'statistics' => [
                    'order_num' => 1,
                    'order_price' => $price,
                    'duration' => $model->duration,
                    'new_customers' => $new_customers
                ]
            ]);
            $notice = new Notice();
            $MassageOrdersAddress=MassageOrdersAddress::where(['orders_id'=>$model->orders_id])->find();
            $MassageUser = MassageUser::where(['id' => $model->uid])->find();
            $name = $MassageUser->nickname.'(' . $model->uid . ')';
            if ($MassageOrdersAddress) {
                $name = $MassageOrdersAddress['name'].'(' . $model->uid . ')';
                $notice->addUSER($MassageOrdersAddress->mobile, null);
            }
            $MassageUserWechat=MassageUserWechat::where(['uid'=>$model->uid])->find();
            if ($MassageUserWechat) {
                $notice->addUSER(null, $MassageUserWechat->openid);
            }
            if ($MassageUserT) {
                $notice->addTECHNICIAN($MassageUserT->mobile, $MassageUserT->openid);
            }
            $MassageService = MassageService::where(['id' => $model->service_id])->find();
            $MassageOrdersAddress = MassageOrdersAddress::where(['orders_id' => $model->orders_id])->find();
            $notice->saas_appid = $model->saas_appid;
            $notice->type = NoticeType::SERVICE_END['value'];
            $notice->setData([
                'state' => ServiceState::FINISH['text'],
                'title' => $MassageService->title,
                'trade' => $MassageOrders->trade,
                'as_id' => $model->id,
                'name' => $name,
                'technician' => $MassageUserT->nickname . '(' . $model->technician_id . ')',
            ]);
            $notice->send();
            Db::commit();
        } catch (\Throwable $th) {
            Db::rollback();
            throw $th;
        }
    }
}
